package com.openvid.webrtc.openvid.websocket;

import android.util.Log;

import com.neovisionaries.ws.client.WebSocket;
import com.neovisionaries.ws.client.WebSocketException;
import com.neovisionaries.ws.client.WebSocketFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class OpenVidWebSocket implements IWebSocket {

    private static final String TAG = "WebSocket";

    private WebSocket mWebsocket;

    private IWebSocketCallback mCallback;
    private boolean mWebsocketCancelled = false;

    public OpenVidWebSocket(IWebSocketCallback callback) {
        mCallback = callback;
    }

    @Override
    public void sendMsg(String msg) {
        mWebsocket.sendText(msg);
    }

    @Override
    public boolean connect(String sessionToken) {
        try {
            WebSocketFactory factory = new WebSocketFactory();
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, mTrustManagers, new SecureRandom());
            factory.setSSLContext(sslContext);
            factory.setVerifyHostname(false);
            mWebsocket = factory.createSocket(getWsAddress(sessionToken));
            mWebsocket.addListener(new AbsWeSocketListener() {
                @Override
                public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
                    Log.i(TAG, "onConnected");
                    doConnectAfterAction();
                }

                @Override
                public void onTextMessage(WebSocket websocket, String text) throws Exception {
                    Log.i(TAG, "onTextMessage:" + text);
                    onTextMessageReceived(text);
                }
            });
            mWebsocket.connect();
            return true;
        } catch (KeyManagementException | NoSuchAlgorithmException | IOException | WebSocketException e) {
            mWebsocketCancelled = true;
            return false;
        }
    }

    @Override
    public void disConnect() {
        mWebsocketCancelled=true;
        if (mWebsocket!=null&&mWebsocket.isOpen()){
            mWebsocket.disconnect();
        }
    }


    private void doConnectAfterAction() {
        if (mCallback != null) {
            mCallback.onConnected();
        }
    }

    private void onTextMessageReceived(String text) {
        if (mCallback != null) {
            mCallback.onTextMessageReceived(text);
        }
    }


    //--------------------------------------
    private static String getWsAddress(String token) {
        String wsUri;
        try {
            Log.e(TAG, "session:" + token);
            URI url = new URI(token);
            if (url.getPort() > -1) {
                wsUri = "wss" + "://" + url.getHost() + ":" + url.getPort() + "/openvidu";
            } else {
                wsUri = "wss" + "://" + url.getHost() + "/openvidu";
            }
            return wsUri;
        } catch (URISyntaxException e) {
            Log.e(TAG, "Wrong URL", e);
            e.printStackTrace();
            return "";
        }
    }

    private static final TrustManager[] mTrustManagers = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                @Override
                public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws
                        CertificateException {
                    Log.i(TAG, ": authType: " + authType);
                }

                @Override
                public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws
                        CertificateException {
                    Log.i(TAG, ": authType: " + authType);
                }
            }
    };
}
